package com.vietnam.power.service.impl;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.MimeMessage;
import javax.mail.search.FlagTerm;

import org.apache.commons.lang.StringUtils;
import org.springframework.mail.javamail.JavaMailSenderImpl;

import com.vietnam.power.constant.GeneralConstant;
import com.vietnam.power.domain.MessageInfo;
import com.vietnam.power.service.MailService;

public class MailServiceImpl extends JavaMailSenderImpl implements MailService {

	public void sendEmail(MimeMessage mimeMessage, String username, String password) {
		setUsername(username);
		setPassword(password);
		super.send(mimeMessage);
	}

	@Override
	public MimeMessage createMimeMessage() {
		return super.createMimeMessage();
	}

	public List<MessageInfo> fetchEmail(String username, String password) throws Exception {
		List<MessageInfo> messageInfos = new ArrayList<MessageInfo>();
		// create properties field
		Properties properties = new Properties();
		properties.put("mail.store.protocol", "imaps");
		Session emailSession = Session.getDefaultInstance(properties, null);
		emailSession.setDebug(true);

		// create the POP3 store object and connect with the pop server
		Store store = emailSession.getStore("imaps");

		store.connect("imap.gmail.com", username, password);
		// create the folder object and open it
		Folder inbox = store.getFolder("INBOX");
		inbox.open(Folder.READ_WRITE);

		// retrieve the messages from the folder in an array and print it
		// Message[] messages = emailFolder.getMessages();
		FlagTerm ft = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
		Message messages[] = inbox.search(ft);

		for (Message m : messages) {
			MessageInfo messageInfo = new MessageInfo();
			Address[] a;
			// FROM
			if ((a = m.getFrom()) != null) {
				String from = StringUtils.EMPTY;
				for (int j = 0; j < a.length; j++) {
					from += a[j].toString().substring(a[j].toString().indexOf("<")+1,a[j].toString().indexOf(">"));
					if (j > 0 && j < a.length - 1) {
						from += GeneralConstant.SEMICOLON;
					}
				}
				messageInfo.setFrom(from);
			}

			// TO
			if ((a = m.getRecipients(Message.RecipientType.TO)) != null) {
				String to = StringUtils.EMPTY;
				for (int j = 0; j < a.length; j++) {
					to += a[j].toString();
					if (j > 0 && j < a.length - 1) {
						to += GeneralConstant.SEMICOLON;
					}
				}

				messageInfo.setTo(to);
			}
			// cc
			if ((a = m.getRecipients(Message.RecipientType.CC)) != null) {
				String cc = StringUtils.EMPTY;
				for (int j = 0; j < a.length; j++) {
					cc += a[j].toString();
					if (j > 0 && j < a.length - 1) {
						cc += GeneralConstant.SEMICOLON;
					}
				}

				messageInfo.setCc(cc);
			}

			// SUBJECT
			if (m.getSubject() != null) {
				messageInfo.setSubject(m.getSubject());
			}

			Multipart mp = (Multipart) m.getContent();
			BodyPart bp = mp.getBodyPart(0);
			messageInfo.setContent(bp.getContent().toString());
			/*
			 * MessageInfo info = writePart(message); if
			 * (StringUtils.isNotBlank(info.getSubject())) {
			 * messageInfos.add(writePart(message)); }
			 */

			messageInfos.add(messageInfo);
		}

		// close the store and folder objects
		inbox.close(false);
		store.close();

		return messageInfos;
	}

	/*
	 * This method checks for content-type based on which, it processes and
	 * fetches the content of the message
	 */
	private MessageInfo writePart(Part p) throws Exception {
		MessageInfo messageInfo = new MessageInfo();
		if (p instanceof Message) {
			// Call methos writeEnvelope
			messageInfo = writeEnvelope((Message) p);
		}
		// check if the content is plain text
		if (p.isMimeType("text/plain")) {
			messageInfo.setContent((String) p.getContent());
		}
		// check if the content has attachment
		else if (p.isMimeType("multipart/*")) {
			System.out.println("This is a Multipart");
			System.out.println("---------------------------");
			Multipart mp = (Multipart) p.getContent();
			int count = mp.getCount();
			for (int i = 0; i < count; i++) {
				// writePart(mp.getBodyPart(i));
			}
		}
		// check if the content is a nested message
		else if (p.isMimeType("message/rfc822")) {
			System.out.println("This is a Nested Message");
			System.out.println("---------------------------");
			// writePart((Part) p.getContent());
		}
		// check if the content is an inline image
		else if (p.isMimeType("image/jpeg")) {
			System.out.println("--------> image/jpeg");
			Object o = p.getContent();

			InputStream x = (InputStream) o;
			// Construct the required byte array
			System.out.println("x.length = " + x.available());
			int i = 0;
			byte[] bArray = new byte[x.available()];

			while ((i = (int) ((InputStream) x).available()) > 0) {
				int result = (int) (((InputStream) x).read(bArray));
				if (result == -1)
					break;
			}
			FileOutputStream f2 = new FileOutputStream("/tmp/image.jpg");
			f2.write(bArray);
		} else if (p.getContentType().contains("image/")) {
			System.out.println("content type" + p.getContentType());
			java.io.File f = new java.io.File("image" + new Date().getTime() + ".jpg");
			DataOutputStream output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
			com.sun.mail.util.BASE64DecoderStream test = (com.sun.mail.util.BASE64DecoderStream) p.getContent();
			byte[] buffer = new byte[1024];
			int bytesRead;
			while ((bytesRead = test.read(buffer)) != -1) {
				output.write(buffer, 0, bytesRead);
			}
		} else {
			Object o = p.getContent();
			if (o instanceof String) {
				System.out.println("This is a string");
				System.out.println("---------------------------");
				System.out.println((String) o);
			} else if (o instanceof InputStream) {
				System.out.println("This is just an input stream");
				System.out.println("---------------------------");
				InputStream is = (InputStream) o;
				is = (InputStream) o;
				int c;
				while ((c = is.read()) != -1)
					System.out.write(c);
			} else {
				System.out.println("This is an unknown type");
				System.out.println("---------------------------");
				System.out.println(o.toString());
			}
		}

		return messageInfo;
	}

	/*
	 * This method would print FROM,TO and SUBJECT of the message
	 */
	private MessageInfo writeEnvelope(Message m) throws Exception {
		MessageInfo messageInfo = new MessageInfo();
		Address[] a;
		// FROM
		if ((a = m.getFrom()) != null) {
			String from = StringUtils.EMPTY;
			for (int j = 0; j < a.length; j++) {
				from += a[j].toString();
				if (j > 0 && j < a.length - 1) {
					from += GeneralConstant.SEMICOLON;
				}
			}
			messageInfo.setFrom(from);
		}

		// TO
		if ((a = m.getRecipients(Message.RecipientType.TO)) != null) {
			String to = StringUtils.EMPTY;
			for (int j = 0; j < a.length; j++) {
				to += a[j].toString();
				if (j > 0 && j < a.length - 1) {
					to += GeneralConstant.SEMICOLON;
				}
			}

			messageInfo.setTo(to);
		}

		// SUBJECT
		if (m.getSubject() != null) {
			messageInfo.setSubject(m.getSubject());
		}

		return messageInfo;
	}

}
